package com.ruoyi.coal.modules.coalpile.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.coal.common.utils.R;
import com.ruoyi.coal.modules.coalpile.mapper.AttributeValueMapper;
import com.ruoyi.coal.modules.coalpile.mapper.CoalYardInfoDao;
import com.ruoyi.coal.modules.coalpile.domain.Attribute;
import com.ruoyi.coal.modules.coalpile.domain.AttributeValue;
import com.ruoyi.coal.modules.coalpile.domain.vo.AttributeValueVo;
import com.ruoyi.coal.modules.coalpile.domain.vo.YardPileDataVo;
import com.ruoyi.coal.modules.coalpile.domain.vo.numUpdateVo;
import com.ruoyi.coal.modules.coalpile.domain.vo.schemeVo;
import com.ruoyi.coal.modules.coalpile.service.AttributeService;
import com.ruoyi.coal.modules.coalpile.service.AttributeValueService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.enums.DataSourceType;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@RequestMapping({"/attributeAndValue"})
@DataSource(value = DataSourceType.SLAVE)
public class AttributeValueController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(com.ruoyi.coal.modules.coalpile.controller.AttributeValueController.class);

    @Autowired
    private AttributeValueService attributeValueService;

    @Autowired
    private AttributeService AttributeService;

    @Autowired
    private AttributeValueMapper AttributeValueMapper;

    @Resource
    private CoalYardInfoDao coalYardInfoDao;

    @Value("${pythonAPI.ip}")
    private String pythonIp;

    @PostMapping({"/saveOrUpdate"})
    public R saveOrUpdate(@RequestBody AttributeValue attributeValue) {
        QueryWrapper<AttributeValue> queryWrapper = new QueryWrapper();
        queryWrapper.eq("attribute_id", attributeValue.getAttributeId());
        queryWrapper.eq("yard_id", attributeValue.getYardId());
        queryWrapper.eq("pile_id", attributeValue.getPileId());
        boolean savedOrUpdate = this.attributeValueService.saveOrUpdate(attributeValue, (Wrapper)queryWrapper);
        if (savedOrUpdate)
            return R.ok("操作成功");
        return R.error("操作失败");
    }

    @PostMapping({"/saveOrUpdateAll"})
    public R saveOrUpdateAll(@RequestBody String valueAndAttribute) {
        try {
            JSONObject jsonObject = new JSONObject(valueAndAttribute);
            int yardId = jsonObject.getInt("yardId");
            JSONObject andAttribute = jsonObject.getJSONObject("valueAndAttribute");
            List<String> successMessages = new ArrayList<>();
            List<String> errorMessages = new ArrayList<>();
            andAttribute.keySet().forEach(key -> {
                String id = key.toString();
                String value = andAttribute.getString(id);
                AttributeValue attributeValue = new AttributeValue();
                attributeValue.setAttributeId(Integer.valueOf(Integer.parseInt(id)));
                attributeValue.setValueString(value);
                attributeValue.setYardId(Integer.valueOf(yardId));
                boolean isSaved = this.attributeValueService.saveOrUpdate(attributeValue);
                if (isSaved) {
                    successMessages.add("属性ID" + id + "保存或更新成功");
                } else {
                    errorMessages.add("属性ID" + id + "保存或更新失败" );
                }
            });
            R r = new R();
            if (errorMessages.isEmpty()) {
                r.put("code", Integer.valueOf(0));
                r.put("msg", "所有属性均保存或更新成功");
                if (!successMessages.isEmpty())
                    r.put("details", successMessages);
            } else {
                r.put("code", Integer.valueOf(500));
                r.put("msg", "所有属性均保存或更新失败");
                        r.put("errors", errorMessages);
            }
            return r;
        } catch (JSONException e) {
            R r = new R();
            r.put("code", Integer.valueOf(400));
            r.put("msg", "无效的JSON格式");
            return r;
        }
    }

    @PostMapping({"/updateAttribute"})
    private R updateAttribute(@RequestBody Attribute attribute) {
        boolean b = this.AttributeService.updateById(attribute);
        if (b)
            return R.ok("操作成功");
        return R.error("操作失败");
    }

    @PostMapping({"/addAttribute"})
    public R addAttribute(@RequestBody Attribute attribute) {
        boolean savedOrUpdate = this.AttributeService.saveOrUpdate(attribute);
        if (savedOrUpdate)
            return R.ok("操作成功");
        return R.error("操作失败");
    }

    @PostMapping({"/updateAttributeAll"})
    public R updateAttribute(@RequestBody numUpdateVo numUpdateVo1) {
        boolean isAllSuccess = true;
        Integer pileId = numUpdateVo1.getPileId();
        Integer yardId = numUpdateVo1.getYardId();
        Map<Integer, Object> value = numUpdateVo1.getValue();
        for (Map.Entry<Integer, Object> entry : value.entrySet()) {
            Integer attributeId = entry.getKey();
            try {
                boolean isSaveSuccess;
                if (attributeId.equals(Integer.valueOf(29)))
                    continue;
                if (attributeId.equals(Integer.valueOf(28))) {
                    QueryWrapper<AttributeValue> queryWrapperVolume = new QueryWrapper();
                    queryWrapperVolume.eq("pile_id", pileId);
                    queryWrapperVolume.eq("yard_id", yardId);
                    queryWrapperVolume.eq("attribute_id", Integer.valueOf(27));
                    AttributeValue volume = (AttributeValue)this.attributeValueService.getOne((Wrapper)queryWrapperVolume);
                    QueryWrapper<AttributeValue> queryWrapperWeight = new QueryWrapper();
                    queryWrapperWeight.eq("pile_id", pileId);
                    queryWrapperWeight.eq("yard_id", yardId);
                    queryWrapperWeight.eq("attribute_id", Integer.valueOf(29));
                    AttributeValue weight = (AttributeValue)this.attributeValueService.getOne((Wrapper)queryWrapperWeight);
                    weight.setValueString(String.format("%.3f", new Object[] { Double.valueOf(Double.parseDouble((String)entry.getValue()) * Double.parseDouble(volume.getValueString())) }));
                    this.attributeValueService.update(weight, (Wrapper)queryWrapperWeight);
                }
                Object valueObj = entry.getValue();
                AttributeValue attributeValue = new AttributeValue();
                attributeValue.setPileId(pileId);
                attributeValue.setYardId(yardId);
                attributeValue.setAttributeId(attributeId);
                String stringValue = (String)valueObj;
                attributeValue.setValueString(stringValue);
                QueryWrapper<AttributeValue> queryWrapper = new QueryWrapper();
                queryWrapper.eq("pile_id", pileId);
                queryWrapper.eq("yard_id", yardId);
                queryWrapper.eq("attribute_id", attributeId);
                AttributeValue one = (AttributeValue)this.attributeValueService.getOne((Wrapper)queryWrapper);
                if (one == null) {
                    isSaveSuccess = this.attributeValueService.save(attributeValue);
                } else {
                    isSaveSuccess = this.attributeValueService.update(attributeValue, (Wrapper)queryWrapper);
                }
                if (!isSaveSuccess)
                    isAllSuccess = false;
            } catch (NumberFormatException numberFormatException) {}
        }
        if (isAllSuccess)
            return R.ok("操作成功");
        return R.error("操作失败");
    }

    @PostMapping({"/getAttribute"})
    public List getAttribute() {
        return this.AttributeService.list();
    }

    @PostMapping({"/getAttributeByYardId"})
    public List getAttribute(@RequestBody AttributeValue attributeValue) {
        QueryWrapper<AttributeValue> queryWrapper = new QueryWrapper();
        queryWrapper.eq("yard_id", attributeValue.getYardId());
        return this.attributeValueService.list((Wrapper)queryWrapper);
    }

    @PostMapping({"/removeAttribute"})
    public R removeAttribute(@RequestBody Attribute attribute) {
        boolean attributeRemove = this.AttributeService.removeById(Integer.valueOf(attribute.getId()));
        QueryWrapper<AttributeValue> queryWrapper = new QueryWrapper();
        queryWrapper.eq("attribute_id", Integer.valueOf(attribute.getId()));
        boolean attributeValueRemove = this.attributeValueService.remove((Wrapper)queryWrapper);
        if (attributeRemove && attributeValueRemove)
            return R.ok("操作成功");
        return R.error("操作失败");
    }

    @PostMapping({"/getAllAttributeValue"})
    private R getAllAttributeValue() {
        List<Map<String, Object>> attributeValue = this.AttributeValueMapper.getAttributeValue();
        List<Map<String, Object>> filteredAttributeValue = (List<Map<String, Object>>)attributeValue.stream().filter(map -> (!"体积".equals(map.get("attribute_name")) && !"密度".equals(map.get("attribute_name")) && !"重量".equals(map.get("attribute_name")))).collect(Collectors.toList());
                Map<Integer, List<Map<String, Object>>> groupedByValue = (Map<Integer, List<Map<String, Object>>>)filteredAttributeValue.stream().collect(Collectors.groupingBy(map -> (Integer)map.get("pile_id"),

                        Collectors.toList()));
        return R.ok().put("data", groupedByValue);
    }

    @PostMapping({"/getAllYardTon"})
    public R getAllYardTon() {
        List<YardPileDataVo> yardPileDataVos = this.AttributeValueMapper.selectAllPileTon();
        return R.ok().put("data", yardPileDataVos);
    }

    @PostMapping({"/getScheme"})
    public R getScheme(@RequestBody schemeVo schemeVo1) {
        switch (schemeVo1.getNumber().intValue()) {
            case 1:
                return getSchemeByTimeAndYardId(schemeVo1);
            case 2:
                return getSchemeByTimeAndYardId(schemeVo1);
            case 3:
                return getSchemeByTimeAndYardId(schemeVo1);
        }
        return null;
    }

    @PostMapping({"/getPileAttributeByYardIdOrderByPileId"})
    public Map<Integer, List<AttributeValue>> getPileAttributeByYardIdOrderByPileId(@RequestBody AttributeValue attributeValue) {
        QueryWrapper<AttributeValue> queryWrapper = new QueryWrapper();
        queryWrapper.eq("yard_id", attributeValue.getYardId());
        List<AttributeValue> list = this.attributeValueService.list((Wrapper)queryWrapper);
        Map<Integer, List<AttributeValue>> groupedByPileId = new HashMap<>();
        for (AttributeValue value : list) {
            Integer pileId = value.getPileId();
            if (!groupedByPileId.containsKey(pileId))
                groupedByPileId.put(pileId, new ArrayList<>());
            ((List<AttributeValue>)groupedByPileId.get(pileId)).add(value);
        }
        return groupedByPileId;
    }

    public R getSchemeByTimeAndYardId(schemeVo schemeVo1) {
        List<AttributeValueVo> selectedPiles = new ArrayList<>();
        double totalDemand = schemeVo1.getTon() * schemeVo1.getValue();
        double currentDemand = totalDemand;
        for (Integer coalFieldId : schemeVo1.getCoalFieldId()) {
            List<AttributeValue> pilesSortedByTime = this.attributeValueService.list((Wrapper)((QueryWrapper)((QueryWrapper)(new QueryWrapper())
                    .eq("yard_id", coalFieldId))
                    .eq("attribute_id", Integer.valueOf(26)))
                    .orderByDesc("value_string"));
            if (!pilesSortedByTime.isEmpty()) {
                for (AttributeValue pile : pilesSortedByTime) {
                    double useWeight;
                    int pileId = pile.getPileId().intValue();
                    AttributeValue weightInfo = new AttributeValue();
                    AttributeValue value = new AttributeValue();
                    weightInfo = (AttributeValue)this.attributeValueService.getOne((Wrapper)((QueryWrapper)((QueryWrapper)(new QueryWrapper())
                            .eq("pile_id", Integer.valueOf(pileId)))
                            .eq("yard_id", coalFieldId))
                            .eq("attribute_id", Integer.valueOf(29)));
                    if (weightInfo == null)
                        continue;
                    if (schemeVo1.getNumber().intValue() == 2) {
                        value = (AttributeValue)this.attributeValueService.getOne((Wrapper)((QueryWrapper)((QueryWrapper)(new QueryWrapper())
                                .eq("pile_id", Integer.valueOf(pileId)))
                                .eq("yard_id", coalFieldId))
                                .eq("attribute_id", Integer.valueOf(33)));
                        if (value == null)
                            continue;
                    }
                    if (schemeVo1.getNumber().intValue() == 3) {
                        value = (AttributeValue)this.attributeValueService.getOne((Wrapper)((QueryWrapper)((QueryWrapper)(new QueryWrapper())
                                .eq("pile_id", Integer.valueOf(pileId)))
                                .eq("yard_id", coalFieldId))
                                .eq("attribute_id", Integer.valueOf(31)));
                        if (value == null)
                            continue;
                    }
                    double weight = Double.parseDouble(weightInfo.getValueString());
                    if (schemeVo1.getNumber().intValue() == 1) {
                        value = (AttributeValue)this.attributeValueService.getOne((Wrapper)((QueryWrapper)((QueryWrapper)(new QueryWrapper())
                                .eq("pile_id", Integer.valueOf(pileId)))
                                .eq("yard_id", coalFieldId))
                                .eq("attribute_id", Integer.valueOf(30)));
                        if (value == null)
                            continue;
                    }
                    double heatValue = Double.parseDouble(value.getValueString());
                    double pileTonAndHot = weight * heatValue;
                    if (pileTonAndHot >= currentDemand) {
                        useWeight = currentDemand / heatValue;
                        currentDemand = 0.0D;
                    } else {
                        useWeight = weight;
                        currentDemand -= weight * heatValue;
                    }
                    AttributeValue pileName = (AttributeValue)this.attributeValueService.getOne((Wrapper)((QueryWrapper)((QueryWrapper)(new QueryWrapper())
                            .eq("pile_id", Integer.valueOf(pileId)))
                            .eq("yard_id", coalFieldId))
                            .eq("attribute_id", Integer.valueOf(23)));
                    AttributeValue batch = (AttributeValue)this.attributeValueService.getOne((Wrapper)((QueryWrapper)((QueryWrapper)(new QueryWrapper())
                            .eq("pile_id", Integer.valueOf(pileId)))
                            .eq("yard_id", coalFieldId))
                            .eq("attribute_id", Integer.valueOf(25)));
                    String name = " ";
                    if (pileName != null)
                        name = pileName.getValueString();
                    AttributeValueVo valueVo = new AttributeValueVo();
                    valueVo.setYardId(coalFieldId.intValue());
                    valueVo.setPileId(pileId);
                    valueVo.setVlaue(heatValue);
                    valueVo.setWeight(weight);
                    valueVo.setUseWeight(useWeight);
                    valueVo.setPileName(name);
                    valueVo.setBatch(batch.getValueString());
                    selectedPiles.add(valueVo);
                    if (currentDemand <= 0.0D)
                        break;
                }
                if (currentDemand <= 0.0D)
                    break;
            }
        }
        if (currentDemand > 0.0D)
            return R.error("无法完全满足需求，剩余需求："+ (currentDemand / schemeVo1.getValue()) + "吨");
        return R.ok().put("data", selectedPiles);
    }

    private AttributeValue getAttributeValueByPileAndAttribute(int pileId, int attributeId) {
        QueryWrapper<AttributeValue> wrapper = new QueryWrapper();
        wrapper.eq("pile_id", Integer.valueOf(pileId));
        wrapper.eq("attribute_id", Integer.valueOf(attributeId));
        return (AttributeValue)this.attributeValueService.getOne((Wrapper)wrapper);
    }

    private List<AttributeValue> getSchemeForLowSulfur(schemeVo schemeVo1) {
        List<AttributeValue> heatValues = this.attributeValueService.list((Wrapper)((QueryWrapper)(new QueryWrapper())
                .eq("attribute_id", Integer.valueOf(2)))
                .orderByAsc("value_string"));
        List<AttributeValue> result = new ArrayList<>();
        double remainingNeeded = schemeVo1.getTon();
        for (AttributeValue heatValue : heatValues) {
            AttributeValue weightValue = getAttributeValueByPileAndAttribute(heatValue.getPileId().intValue(), 4);
            double parseDouble = Double.parseDouble(weightValue.getValueString());
            if (weightValue != null && parseDouble > 0.0D) {
                double currentWeight = parseDouble;
                if (currentWeight >= remainingNeeded) {
                    result.add(weightValue);
                    remainingNeeded = 0.0D;
                    break;
                }
                result.add(weightValue);
                remainingNeeded -= currentWeight;
            }
        }
        return result;
    }

    private List<AttributeValue> getSchemeForLowAsh(schemeVo schemeVo1) {
        List<AttributeValue> heatValues = this.attributeValueService.list((Wrapper)((QueryWrapper)(new QueryWrapper())
                .eq("attribute_id", Integer.valueOf(11)))
                .orderByAsc("value_string"));
        List<AttributeValue> result = new ArrayList<>();
        double remainingNeeded = schemeVo1.getTon();
        for (AttributeValue heatValue : heatValues) {
            AttributeValue weightValue = getAttributeValueByPileAndAttribute(heatValue.getPileId().intValue(), 4);
            double parseDouble = Double.parseDouble(weightValue.getValueString());
            if (weightValue != null && parseDouble > 0.0D) {
                double currentWeight = parseDouble;
                if (currentWeight >= remainingNeeded) {
                    result.add(weightValue);
                    remainingNeeded = 0.0D;
                    break;
                }
                result.add(weightValue);
                remainingNeeded -= currentWeight;
            }
        }
        return result;
    }

    @GetMapping({"/getScanPileAttributeByXY"})
    public R getScanPileAttributeByXY(@RequestParam("xPoint") double x, @RequestParam("yPoint") double y, @RequestParam("coalYardId") Integer coalYardId) {
        int coalYardNum = this.coalYardInfoDao.getCoalYardId().size();
        int[] ports = new int[coalYardNum];
        for (int i = 0; i < coalYardNum; i++)
            ports[i] = 8000 + i;
        int port = ports[(coalYardId.intValue() - 1) % coalYardNum];
        String url = "http://" + this.pythonIp + ":" + port + "/coal/getScanPileAttributeByXY";
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        LinkedMultiValueMap linkedMultiValueMap = new LinkedMultiValueMap();
        linkedMultiValueMap.add("coalYardId", coalYardId);
        linkedMultiValueMap.add("xPoint", Double.valueOf(x));
        linkedMultiValueMap.add("yPoint", Double.valueOf(y));
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, Object>> param = new HttpEntity(linkedMultiValueMap, (MultiValueMap)headers);
        ResponseEntity<String> response = null;
        try {
            response = restTemplate.postForEntity(url, param, String.class, new Object[0]);
        } catch (Exception e) {
            System.out.println("调用python接口失败，获取属性失败"+ e.getMessage());
            return R.error("调用python接口失败，获取属性失败");
        }
        String body = (String)response.getBody();
        Map parseObject = (Map)JSON.parseObject(body, Map.class);
        String colorHex = "";
        if (parseObject.get("color_hex") != null) {
            colorHex = (String)parseObject.get("color_hex");
        } else {
            return R.error("为获取到对应的颜色属性");
        }
        AttributeValue attributeValue = (AttributeValue)this.attributeValueService.getOne((Wrapper)((QueryWrapper)((QueryWrapper)(new QueryWrapper())
                .eq("value_string", colorHex))
                .eq("yard_id", coalYardId))
                .last("LIMIT 1"));
        if (attributeValue != null && attributeValue.getPileId() != null) {
            List<AttributeValue> attributeValues = this.attributeValueService.list((Wrapper)(new QueryWrapper()).eq("pile_id", attributeValue.getPileId()));
            return R.ok().put("data", attributeValues);
        }
        return R.error("为获取到对应的没对");
    }
}

